home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / ZIP_1_0.lha / src / input.c < prev    next >
C/C++ Source or Header  |  1992-10-13  |  8KB  |  373 lines

  1. /*
  2.  * input.c
  3.  *
  4.  * Input routines
  5.  *
  6.  * Mark Howell 28-Jul-1992 V1.0
  7.  *
  8.  */
  9.  
  10. #include "ztypes.h"
  11.  
  12. /* Statically defined word separator list */
  13.  
  14. static const char *separators = " \t\n\f.,?";
  15.  
  16. #ifdef __STDC__
  17. static const char *next_token (const char *, const char **, int *);
  18. static zword_t find_word (int, const char *);
  19. static void get_line (char *);
  20. #else
  21. static const char *next_token ();
  22. static zword_t find_word ();
  23. static void get_line ();
  24. #endif
  25.  
  26. /*
  27.  * read_character
  28.  *
  29.  * Read one character with optional timeout
  30.  *
  31.  */
  32.  
  33. #ifdef __STDC__
  34. void read_character (int argc, zword_t *args)
  35. #else
  36. void read_character (argc, args)
  37. int argc;
  38. zword_t *args;
  39. #endif
  40. {
  41.  
  42.     /* Haven't done timeouts yet */
  43.  
  44.     if (argc != 1)
  45.         fatal ("Unimplemented timeout function");
  46.  
  47.     /* Reset line count and character count */
  48.  
  49.     lines_written = 0;
  50.     char_count = screen_cols - RIGHT_MARGIN;
  51.  
  52.     /* Read n characters, only 1 supported */
  53.  
  54.     if (args[0] == 1)
  55.         store_operand (input_character ());
  56.     else
  57.         store_operand (0);
  58.  
  59. }/* read_character */
  60.  
  61. /*
  62.  * read_line
  63.  *
  64.  * Read a line of input with optional timeout. The token buffer needs some
  65.  * additional explanation. The first byte is the maximum number of tokens
  66.  * allowed. The second byte is set to the actual number of token read. Each
  67.  * token is composed of 3 fields. The first (word) field contains the word
  68.  * offset in the dictionary, the second (byte) field contains the token length,
  69.  * and the third (byte) field contains the start offset of the token in the
  70.  * character buffer.
  71.  *
  72.  */
  73.  
  74. #ifdef __STDC__
  75. void read_line (int argc, zword_t *args)
  76. #else
  77. void read_line (argc, args)
  78. int argc;
  79. zword_t *args;
  80. #endif
  81. {
  82.     int words, token_length;
  83.     char *cbuf, *tbuf, *tp;
  84.     const char *cp, *token;
  85.     zword_t word;
  86.  
  87.     /* Haven't done timeouts yet */
  88.  
  89.     if (argc != 2)
  90.         fatal ("Unimplemented timeout function");
  91.  
  92.     /* Refresh status line */
  93.  
  94.     if (h_type == V3)
  95.         display_status_line ();
  96.  
  97.     /* Flush any buffered output before read */
  98.  
  99.     flush_buffer (FALSE);
  100.  
  101.     /* Reset line count */
  102.  
  103.     lines_written = 0;
  104.  
  105.     /* Initialise character and token buffer pointers */
  106.  
  107.     cbuf = (char *) &datap[args[0]];
  108.     tbuf = (char *) &datap[args[1]];
  109.  
  110.     /* Read the line then script it */
  111.  
  112.     get_line (cbuf);
  113.     script_line (&cbuf[1]);
  114.  
  115.     /* Initialise word count and pointers */
  116.  
  117.     words = 0;
  118.     cp = cbuf + 1;
  119.     tp = tbuf + 2;
  120.  
  121.     /* Tokenise the line */
  122.  
  123.     do {
  124.  
  125.         /* Skip to next token */
  126.  
  127.         cp = next_token (cp, &token, &token_length);
  128.         if (token_length)
  129.  
  130.             /* If still space in token buffer then store word */
  131.  
  132.             if (words <= tbuf[0]) {
  133.  
  134.                 /* Get the word offset from the dictionary */
  135.  
  136.                 word = find_word (token_length, token);
  137.  
  138.                 /* Store the dictionary offset, token length and offset */
  139.  
  140.                 tp[0] = (char) (word >> 8);
  141.                 tp[1] = (char) (word & 0xff);
  142.                 tp[2] = (char) token_length;
  143.                 tp[3] = (char) (token - cbuf);
  144.  
  145.                 /* Step to next token position and count the word */
  146.  
  147.                 tp += 4;
  148.                 words++;
  149.             } else {
  150.  
  151.                 /* Moan if token buffer space exhausted */
  152.  
  153.                 output_string ("Too many words typed, discarding: ");
  154.                 output_stringnl (token);
  155.             }
  156.     } while (token_length);
  157.  
  158.     /* Store word count */
  159.  
  160.     tbuf[1] = (char) words;
  161.  
  162. }/* read_line */
  163.  
  164. /*
  165.  * next_token
  166.  *
  167.  * Find next token in a string. The token (word) is delimited by a statically
  168.  * defined and a game specific set of word separators. The game specific set
  169.  * of separators look like real word separators, but the parser wants to know
  170.  * about them. An example would be: 'grue, take the axe. go north'. The
  171.  * parser wants to know about the comma and the period so that it can correctly
  172.  * parse the line. The 'interesting' word separators normally appear at the
  173.  * start of the dictionary, and are also put in a separate list in the game
  174.  * file.
  175.  *
  176.  */
  177.  
  178. #ifdef __STDC__
  179. static const char *next_token (const char *s, const char **token, int *length)
  180. #else
  181. static const char *next_token (s, token, length)
  182. const char *s;
  183. const char **token;
  184. int *length;
  185. #endif
  186. {
  187.     int i;
  188.  
  189.     /* Set the token length to zero */
  190.  
  191.     *length = 0;
  192.  
  193.     /* Step through the string looking for separators */
  194.  
  195.     for (; *s; s++) {
  196.  
  197.         /* Look for game specific word separators first */
  198.  
  199.         for (i = 0; punctuation[i] && *s != punctuation[i]; i++)
  200.             ;
  201.  
  202.         /* If a separator is found then return the information */
  203.  
  204.         if (punctuation[i]) {
  205.  
  206.             /* If length has been set then just return the word position */
  207.  
  208.             if (*length)
  209.                 return (s);
  210.             else {
  211.  
  212.                 /* End of word, so set length, token pointer and return string */
  213.  
  214.                 (*length)++;
  215.                 *token = s;
  216.                 return (++s);
  217.             }
  218.         }
  219.  
  220.         /* Look for statically defined separators last */
  221.  
  222.         for (i = 0; separators[i] && *s != separators[i]; i++)
  223.             ;
  224.  
  225.         /* If a separator is found then return the information */
  226.  
  227.         if (separators[i]) {
  228.  
  229.             /* If length has been set then just return the word position */
  230.  
  231.             if (*length)
  232.                 return (++s);
  233.         } else {
  234.  
  235.             /* If first token character then remember its position */
  236.  
  237.             if (*length == 0)
  238.                 *token = s;
  239.             (*length)++;
  240.         }
  241.     }
  242.  
  243.     return (s);
  244.  
  245. }/* next_token */
  246.  
  247. /*
  248.  * find_word
  249.  *
  250.  * Search the dictionary for a word. Just encode the word and binary chop the
  251.  * dictionary looking for it.
  252.  *
  253.  */
  254.  
  255. #ifdef __STDC__
  256. static zword_t find_word (int len, const char *cp)
  257. #else
  258. static zword_t find_word (len, cp)
  259. int len;
  260. const char *cp;
  261. #endif
  262. {
  263.     short word[3];
  264.     int offset, word_index, chop, status;
  265.  
  266.     /* Encode target word */
  267.  
  268.     encode_text (len, cp, word);
  269.  
  270.     /* Calculate the binary chop start position */
  271.  
  272.     word_index = dictionary_size / 2;
  273.     chop = 1;
  274.     do
  275.         chop *= 2;
  276.     while (word_index /= 2);
  277.  
  278.     /* Set the initial position for the binary chop */
  279.  
  280.     word_index = chop - 1;
  281.  
  282.     /* Binary chop until the word is found */
  283.  
  284.     while (chop) {
  285.  
  286.         /* Set next chop step */
  287.  
  288.         chop /= 2;
  289.  
  290.         /* Calculate dictionary offset */
  291.  
  292.         offset = dictionary_offset + (word_index * entry_size);
  293.  
  294.         /* If word matches then return dictionary offset */
  295.  
  296.         if ((status = word[0] - (short) get_word (offset)) == 0 &&
  297.             (status = word[1] - (short) get_word (offset + 2)) == 0 &&
  298.            (h_type == V3 ||
  299.             (status = word[2] - (short) get_word (offset + 4)) == 0))
  300.             return (offset);
  301.  
  302.         /* Set next position depending on direction of overshoot */
  303.  
  304.         if (status > 0) {
  305.             word_index += chop;
  306.  
  307.             /* Deal with end of dictionary case */
  308.  
  309.             if (word_index >= (int) dictionary_size)
  310.                 word_index = dictionary_size - 1;
  311.         } else {
  312.             word_index -= chop;
  313.  
  314.             /* Deal with start of dictionary case */
  315.  
  316.             if (word_index < 0)
  317.                 word_index = 0;
  318.         }
  319.     }
  320.  
  321.     return (0);
  322.  
  323. }/* find_word */
  324.  
  325. /*
  326.  * get_line
  327.  *
  328.  * Read a line of input and lower case it.
  329.  *
  330.  */
  331.  
  332. /* Get rid of macro tolower because of side effects */
  333.  
  334. #ifdef tolower
  335. #undef tolower
  336. #endif
  337.  
  338. #ifdef __STDC__
  339. static void get_line (char *buffer)
  340. #else
  341. static void get_line (buffer)
  342. char *buffer;
  343. #endif
  344. {
  345.     const char *srcp;
  346.     char *destp, columns;
  347.     int i;
  348.  
  349.     /* Set maximum line width to width of screen */
  350.  
  351.     columns = (screen_cols > 127) ? 127 : screen_cols;
  352.     if (buffer[0] <= (columns - RIGHT_MARGIN - 1))
  353.         input[0] = buffer[0];
  354.     else
  355.         input[0] = (columns - RIGHT_MARGIN - 1);
  356.  
  357.     /* Read the line */
  358.  
  359.     input_line ();
  360.  
  361.     /* Convert line to lowercase */
  362.  
  363.     srcp = &input[2];
  364.     destp = &buffer[1];
  365.     for (i = 0; i < input[1]; i++)
  366.         *destp++ = (char) tolower (*srcp++);
  367.  
  368.     /* Zero terminate line */
  369.  
  370.     *destp = '\0';
  371.  
  372. }/* get_line */
  373.